
package visualisation;


import javax.swing.*
import javax.swing.tree.DefaultMutableTreeNode as TreeNode
import groovy.swing.SwingBuilder
import primitives.cluster.*;
import search.util.*;
import search.fitnessfunctions.*;
import bunchbridge.*;

class TreeExplorer{

	static def void main(String[] args){


		String filename = args[0];
		boolean preprocess = false;
		if(args.length >= 2){
			preprocess = true;
		}
		ClusterHead ch = TreeLoader2.loadTreeFromSerial(new File(filename));
		if(ch == null){
			System.err.println("ERROR: Tree loaded from " + args[0] + " is null. Aborting metric dump.");
			System.exit(-0xBAD);
		}
/*		try{
			System.out.print (evaluate(tree));
		}catch(NullPointerException npe){
			System.err.println("Caught a NPE! for file " + args[0]);

			ClusterUtils.prettyPrintTree(tree);
			System.exit(-0xBEEF);
		}
		*/

		

		if(preprocess){
			
			int saved = 0;
			
			def toVisit = [[null,ch]]
			while(!toVisit.isEmpty()){
				def (parent,current) = toVisit.pop();
				
				if(current.encapsulates()){
					
					int numChildren = current.getChildren().size();
					int numNodes = current.getNodes().size();
					if(numChildren ==  1 && parent != null ){
						if(numNodes == 1){
							def newNode = new ClusterLeaf()
							//consider moving ids of current to newnode
							current.getNodes().each{
								newNode.addNode(it);
							}
							parent.addChild(newNode);
							toVisit.push([parent, newNode])						
						}else{
							current.children.each{
								parent.addChild(it)
								toVisit.push([parent, it])
							}
						}					
						parent.deleteChild(current)						
						saved++;
					}else{
						current.children.each{
							toVisit.push([current,it])
						}
					}
					
				}
				
			}
			
			println "Done superfluous edge deletion, saved $saved levels."
			
			int depth = LayeringMQ.maxDepth(ch);

			ClusterHead toEval = LayeringMQ.extendLayers(ch,depth);
			
			
		}


		def swing = new SwingBuilder()
		JTree mboxTree
		JTable fitnessTable
		swing.frame(title: filename, defaultCloseOperation: JFrame.DISPOSE_ON_CLOSE,
		    size: [800, 600], show: true, locationRelativeTo: null) {
		    lookAndFeel("system")
			splitPane {
		        	
				scrollPane(constraints: "left", preferredSize:[160, -1]) {
					fitnessTable = table()
			        }
				scrollPane(constraints:"right"){
			            mboxTree = tree(rootVisible: false)					
				}
			
			}
			["Level", "Clusters", "Fitness","MQ"].each { fitnessTable.model.addColumn(it) }

		}
		HashSet<IClusterLevel> nodesInThisLevel = new HashSet<IClusterLevel>();
		def assignments = [:];
		def mqvals = [:]
		nodesInThisLevel.add(ch);
		double total = 0;
		
		int count = nodesInThisLevel.size();
		
		def ids =[];
		def parents = [:]
		ids = ch.getIDs();
		def level = 0;
//		def nextFitnessNode = fitnessTree.model.root;
		
		while(!nodesInThisLevel.isEmpty() && count > 0){
			HashSet<IClusterLevel> next = new HashSet<IClusterLevel>();
			ClusterHead temp = new ClusterHead(nodesInThisLevel, true);
		
			double fitness=0;
			
			count = 0;
			BunchFitnessAdaptor ff = new BunchFitnessAdaptor("bunch.TurboMQ");

		    	
		    
		        ff.setTree(temp);
		    
			
			fitness =ff.evaluate(temp);
			nodesInThisLevel.each{mqvals[it] = fitness;}
			fitness *=100;
			nodesInThisLevel.each{assignments[it] = fitness;}

			//depth is decremented as we go down the three so the weight increases
			total += fitness;
			
//			def newFitnessNode = new TreeNode(fitness);
//			nextFitnessNode.add(newFitnessNode);
//			nextFitnessNode = newFitnessNode;
			
			def rows = fitnessTable.getModel().addRow([level++, nodesInThisLevel.size(), fitness, fitness/100] as String[]);

			fitnessTable.getModel().fireTableDataChanged();

			for(IClusterLevel c: nodesInThisLevel){

				for(IClusterLevel d: ((ClusterNode)c).getChildren()){
					if(d.encapsulates()){
						
						next.add(d);
//						ids.addAll(d.getIDs());
						parents[c] = d;
						
						if( ((ClusterNode)d).getNodes().size() > 1){
							count++;
						}
					}
				}
			}
			if(count == 0) {
				println "count is zero"
			}
			nodesInThisLevel = next;
		}
		



		mboxTree.model.root.removeAllChildren()

		def top_id = 0;
		println(ch.getIDs())
		ch.getIDs().each{top_id = it}

		def toVisit = [[mboxTree.model.root,ch]];
		
		while(!toVisit.isEmpty()){
			def (parent, current) = toVisit.pop();
			
			def top = 0;
			current.getIDs().each{top = it;}


			if(current.encapsulates()){
				
				def cids=current.getIDs()
				def pids=parents[current];
				if(pids != null){
					pids=pids.getIDs()
				}else{
					pids= "NULL"
				}
				
			//	println "node ${cids}; parent ${pids}"
				def node = new TreeNode("ClusterNode :: "+ top);
				parent.add(node);
				current.children.each{ toVisit.push([node, it]) }
			}else{
				def pn
				current.nodes.each{pn = it}
				
				def node = new TreeNode("ClusterLeaf :: Node ${pn.label}");
				parent.add(node);
				
			}
		}
//		mboxTree.model.root.add(par);
		mboxTree.model.reload(mboxTree.model.root)
//		fitnessTree.model.reload(fitnessTree.model.root)
		
	}
}